package repository

import (
	"context"
	"go-server-demo/ent"
	"go-server-demo/ent/user"
)

type UserRepository struct {
	client *ent.Client
}

func NewUserRepository(client *ent.Client) *UserRepository {
	return &UserRepository{
		client: client,
	}
}

func (r *UserRepository) Create(ctx context.Context, req *CreateUserRequest) (*ent.User, error) {
	return r.client.User.
		Create().
		SetUsername(req.Username).
		SetEmail(req.Email).
		SetPassword(req.Password).
		SetNillablePhone(req.Phone).
		SetStatus(user.Status(req.Status)).
		Save(ctx)
}

func (r *UserRepository) GetByID(ctx context.Context, id int) (*ent.User, error) {
	return r.client.User.
		Query().
		Where(user.ID(id)).
		Only(ctx)
}

func (r *UserRepository) GetByUsername(ctx context.Context, username string) (*ent.User, error) {
	return r.client.User.
		Query().
		Where(user.Username(username)).
		Only(ctx)
}

func (r *UserRepository) Update(ctx context.Context, id int, req *UpdateUserRequest) (*ent.User, error) {
	update := r.client.User.
		UpdateOneID(id)

	if req.Email != nil {
		update.SetEmail(*req.Email)
	}
	if req.Phone != nil {
		update.SetPhone(*req.Phone)
	}
	if req.Status != nil {
		update.SetStatus(user.Status(*req.Status))
	}

	return update.Save(ctx)
}

func (r *UserRepository) Delete(ctx context.Context, id int) error {
	return r.client.User.
		DeleteOneID(id).
		Exec(ctx)
}

func (r *UserRepository) List(ctx context.Context, limit, offset int) ([]*ent.User, error) {
	return r.client.User.
		Query().
		Limit(limit).
		Offset(offset).
		Order(ent.Desc(user.FieldCreatedAt)).
		All(ctx)
}

type CreateUserRequest struct {
	Username string  `json:"username"`
	Email    string  `json:"email"`
	Password string  `json:"password"`
	Phone    *string `json:"phone"`
	Status   string  `json:"status"`
}

type UpdateUserRequest struct {
	Email  *string `json:"email"`
	Phone  *string `json:"phone"`
	Status *string `json:"status"`
}
